package moltencore.game;

import spark.math.Vector2;
import spark.math.Matrix;
import spark.math.Vector3;

import java.util.Queue;
import java.util.LinkedList;

import moltencore.game.bubble.Bubble;

public class Cannon {
	public static enum Direction
	{
		Left(1),
		Right(-1);

		private final int value;

		private Direction(final int value)
		{
			this.value = value;
		}

		int getValue() { return value; }
	}

	private ICannonLoadListener cannonLoadListener;

	private final Vector2 target = new Vector2();
	private Vector2 position = new Vector2();
	private float force;
	private float panningSpeed;
	private Queue<Bubble> cannonBalls = new LinkedList<Bubble>();

	public Cannon(float force, float panningSpeed) {
		this.force = force;
		this.panningSpeed = panningSpeed;
	}

	/**
	 * Loads a bubble into the cannon. If this cannon already contains one or more bubbles the loaded bubble is queued
	 * at the end.
	 * @param bubble Bubble to load the cannon with.
	 */
	public void load(Bubble bubble) {
		cannonBalls.add(bubble);
		//set the position of the cannonball to that of the cannon
		bubble.getPosition().copy(position);
		cannonLoadListener.cannonLoaded(bubble, cannonBalls.size() - 1);
	}

	/**
	 * Fire the oldest Bubble from this cannon with this cannon's force and in the cannon's target direction. If
	 * the cannon is not loaded fires nothing (null).
	 * @return Bubble fired by this cannon. null if cannon is not loaded.
	 */
	public Bubble fire() {
		//get the next cannonball from the queue, if we have none fire null
		Bubble cannonBall = cannonBalls.poll();
		if(cannonBall == null) {
			return null;
		}
		//set the velocity of the fired cannonball to the direction in which the cannon is aiming
		//and fire it with the cannons force
		cannonBall.getVelocity().copy(Vector2.multiply(target, force));
		return cannonBall;
	}

	/**
	 * Move the cannon in the given direction.
	 * @param direction Direction to move the cannon in.
	 * @param elapsedSeconds How many seconds have passed since the last frame.
	 */
	public void move(Direction direction, float elapsedSeconds)
	{
		target.rotate(panningSpeed * elapsedSeconds * direction.getValue());
	}

	public float getForce() {
		return force;
	}

	public void setForce(final float force) {
		this.force = force;
	}

	public float getPanningSpeed() {
		return panningSpeed;
	}

	public void setPanningSpeed(float panningSpeed) {
		this.panningSpeed = panningSpeed;
	}

	public Vector2 getTarget() {
		return target;
	}

	public Vector2 getPosition() {
		return position;
	}

	public void setCannonLoadListener(ICannonLoadListener cannonLoadListener) {
		this.cannonLoadListener = cannonLoadListener;
	}
}
